#ifndef _STATICSTR_H_
#define _STATICSTR_H_

namespace SEngine
{
    constexpr size_t StrLen(const char *str, size_t index = 0) {
        return str[index] == 0 ? index : StrLen(str, index + 1);
    }
    
    constexpr char StrIndex(const char *str, size_t index) {
        return index < StrLen(str) ? str[index] : 0;
    }
    
    // a compile-time string
    template <char tail, char... c>
    struct StaticStr final {
        template <char next>
        using Append = StaticStr<next, c..., tail>;
    
        // compile-time only
        StaticStr() = delete;
    };
    
    template <char... c>
    struct StaticStr<0, c...> final {
        static const char str[];
    
        template <char next>
        using Append = StaticStr<0, c...>;
    
        // compile-time only
        StaticStr() = delete;
    };
    
    template <char... c>
    const char StaticStr<0, c...>::str[]{c..., 0};

    #define SE_STATIC_STR(Str) \
    ( \
        SEngine::StaticStr<SEngine::StrIndex((Str), 0)>::Append<SEngine::StrIndex((Str), 1)> \
            ::Append<SEngine::StrIndex((Str), 2)>::Append<SEngine::StrIndex((Str), 3)> \
            ::Append<SEngine::StrIndex((Str), 4)>::Append<SEngine::StrIndex((Str), 5)> \
            ::Append<SEngine::StrIndex((Str), 6)>::Append<SEngine::StrIndex((Str), 7)> \
            ::Append<SEngine::StrIndex((Str), 8)>::Append<SEngine::StrIndex((Str), 9)> \
            ::Append<SEngine::StrIndex((Str), 10)>::Append<SEngine::StrIndex((Str), 11)> \
            ::Append<SEngine::StrIndex((Str), 12)>::Append<SEngine::StrIndex((Str), 13)> \
            ::Append<SEngine::StrIndex((Str), 14)>::Append<SEngine::StrIndex((Str), 15)> \
            ::Append<SEngine::StrIndex((Str), 16)>::Append<SEngine::StrIndex((Str), 17)> \
            ::Append<SEngine::StrIndex((Str), 18)>::Append<SEngine::StrIndex((Str), 19)> \
            ::Append<SEngine::StrIndex((Str), 20)>::Append<SEngine::StrIndex((Str), 21)> \
            ::Append<SEngine::StrIndex((Str), 22)>::Append<SEngine::StrIndex((Str), 23)> \
            ::Append<SEngine::StrIndex((Str), 24)>::Append<SEngine::StrIndex((Str), 25)> \
            ::Append<SEngine::StrIndex((Str), 26)>::Append<SEngine::StrIndex((Str), 27)> \
            ::Append<SEngine::StrIndex((Str), 28)>::Append<SEngine::StrIndex((Str), 29)> \
            ::Append<SEngine::StrIndex((Str), 30)>::Append<SEngine::StrIndex((Str), 31)> \
            ::Append<SEngine::StrIndex((Str), 32)>::Append<SEngine::StrIndex((Str), 33)> \
            ::Append<SEngine::StrIndex((Str), 34)>::Append<SEngine::StrIndex((Str), 35)> \
            ::Append<SEngine::StrIndex((Str), 36)>::Append<SEngine::StrIndex((Str), 37)> \
            ::Append<SEngine::StrIndex((Str), 38)>::Append<SEngine::StrIndex((Str), 39)> \
            ::Append<SEngine::StrIndex((Str), 40)>::Append<SEngine::StrIndex((Str), 41)> \
            ::Append<SEngine::StrIndex((Str), 42)>::Append<SEngine::StrIndex((Str), 43)> \
            ::Append<SEngine::StrIndex((Str), 44)>::Append<SEngine::StrIndex((Str), 45)> \
            ::Append<SEngine::StrIndex((Str), 46)>::Append<SEngine::StrIndex((Str), 47)> \
            ::Append<SEngine::StrIndex((Str), 48)>::Append<SEngine::StrIndex((Str), 49)> \
            ::Append<SEngine::StrIndex((Str), 50)>::Append<SEngine::StrIndex((Str), 51)> \
            ::Append<SEngine::StrIndex((Str), 52)>::Append<SEngine::StrIndex((Str), 53)> \
            ::Append<SEngine::StrIndex((Str), 54)>::Append<SEngine::StrIndex((Str), 55)> \
            ::Append<SEngine::StrIndex((Str), 56)>::Append<SEngine::StrIndex((Str), 57)> \
            ::Append<SEngine::StrIndex((Str), 58)>::Append<SEngine::StrIndex((Str), 59)> \
            ::Append<SEngine::StrIndex((Str), 60)>::Append<SEngine::StrIndex((Str), 61)> \
            ::Append<SEngine::StrIndex((Str), 62)>::Append<SEngine::StrIndex((Str), 63)> \
            ::str \
    )

} // namespace SEngine


#endif